package git.soulbgm;

import git.soulbgm.utils.IoUtil;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.*;

/**
 * @author SoulBGM
 * @version 1.0
 * @date 2020/5/14 22:55
 */
public class ComposeFileTest {

    public static void main(String[] args) throws Exception {
        String rootPath = "F:\\迅雷下载\\m3u8\\VideoData";
        String[] composeFileArrays = {
                "0c85b7e040358cd658df178941d8ab0a5789dfa9",
                "4d6b33af12409bb8807f87aa1e43857608afbef8",
                "4f36af0bbf6ae0b566ebd41c935a10d1e3968956",
                "33f3933efdb24a4d553de341118098ecbc4ff6ba",
                "39de93375de2aca7e796eedeaff63ec90be636bd",
                "45f0a25dfde7f4094b98624f67e9da824122e0b0",
                "351d7e6b900c917f1dd090f901c4d32100c0675a",
                "1929f772f223adc53c05e85553c04a9a4ff003df",
                "2962d1c7b67a111cd4957e45afb70f847ecd276d",
                "6021e4908413fd292849444a36544e51c12b0899",
                "d3102c59bf746b126260eb92457c1fb63b0c070c",
                "d3819d2d933ed8c385229c4471911e9116f32c17",
                "f4a19652f0ee6ba62bca510247bba1b4881e7c61"
        };
        String prefix = "Y2hlbmppbmdjb25n";
        String encryptionName = "k0";
        for (String fileName : composeFileArrays) {
            System.out.println("开始整合 " + fileName + " 文件");
            HashMap<Integer, String> keyFileMap = new HashMap<>();
            File file = new File(rootPath + File.separator + fileName);
            String[] fileNameArrays = file.list();
            String encryption = null;

            List<String> list = new ArrayList<>(Arrays.asList(fileNameArrays));
            boolean isKey = list.contains(encryptionName);
            if (isKey) {
                list.remove(list.indexOf(encryptionName));
                File encryptionFile = new File(file.getAbsolutePath() + File.separator + encryptionName);
                encryption = IoUtil.getFileContent(encryptionFile);
                if (encryption != null) {
                    System.out.println(encryption);
                }
            }
            list.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    String o1Id = o1.substring(prefix.length());
                    String o2Id = o2.substring(prefix.length());
                    int o1Num = Integer.parseInt(o1Id);
                    int o2Num = Integer.parseInt(o2Id);
                    return Integer.compare(o1Num, o2Num);
                }
            });
            for (int i = 0; i < list.size(); i++) {
                keyFileMap.put(i, file.getAbsolutePath() + File.separator + list.get(i));
            }
            System.out.println(composeFile(rootPath, fileName + ".mp4", encryption, keyFileMap));
        }
    }

    /**
     * 视频片段合成
     */
    public static String composeFile(String rootPath, String fileName, String encryption, HashMap<Integer, String> keyFileMap) throws Exception {
        if (keyFileMap.isEmpty()) {
            return null;
        }

        String fileOutPath = rootPath + File.separator + fileName;
        FileOutputStream fileOutputStream = new FileOutputStream(new File(fileOutPath));
        byte[] bytes = null;
        for (int i = 0; i < keyFileMap.size(); i++) {
            String nodePath = keyFileMap.get(i);
            File file = new File(nodePath);
            if (!file.exists()) {
                continue;
            }

            bytes = IoUtil.toByteArray(nodePath);
            if (encryption != null) {
                bytes = decrypt(bytes, encryption);
            }
            if (bytes != null) {
                fileOutputStream.write(bytes, 0, bytes.length);
            }
        }
        fileOutputStream.flush();
        fileOutputStream.close();

        return fileName;
    }


    /**
     * 解密ts
     *
     * @param sSrc ts文件字节数组
     * @param sKey 密钥
     * @return 解密后的字节数组
     */
    private static byte[] decrypt(byte[] sSrc, String sKey) {
        try {
            // 判断Key是否正确
            if (sKey == null || "".equals(sKey)) {
                return sSrc;
            }
            // 判断Key是否为16位
            if (sKey.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec keySpec = new SecretKeySpec(sKey.getBytes("utf-8"), "AES");
            //如果m3u8有IV标签，那么IvParameterSpec构造函数就把IV标签后的内容转成字节数组传进去
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(new byte[16]);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
            return cipher.doFinal(sSrc);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

}
